﻿// Name:        Common.Threading.debug.js
// Assembly:    AjaxControlToolkit


(function () {

    var scriptName = 'Threading';

    function execute() {



        Type.registerNamespace('Sys.Extended.UI');

        Sys.Extended.UI.DeferredOperation = function (delay, context, callback) {
            // Used to define a cancellable async operation
            // "delay" - the number of milliseconds to delay execution
            // "context" - an object used as the context for the callback method
            // "callback" - the callback method to execute at the end of the delay

            this._delay = delay;
            this._context = context;
            this._callback = callback;
            this._completeCallback = null;
            this._errorCallback = null;
            this._timer = null;
            this._callArgs = null;
            this._isComplete = false;
            this._completedSynchronously = false;
            this._asyncResult = null;
            this._exception = null;
            this._throwExceptions = true;
            this._oncomplete$delegate = Function.createDelegate(this, this._oncomplete);

            // post to ensure that attaching it always gets the port as its context
            this.post = Function.createDelegate(this, this.post);
        }

        Sys.Extended.UI.DeferredOperation.prototype = {

            get_isPending: function () {
                return (this._timer != null);
            },

            get_isComplete: function () {
                return this._isComplete;
            },

            get_completedSynchronously: function () {
                return this._completedSynchronously;
            },

            get_exception: function () {
                return this._exception;
            },

            get_throwExceptions: function () {
                return this._throwExceptions;
            },

            set_throwExceptions: function (value) {
                // Sets whether to throw exceptions
                this._throwExceptions = value;
            },

            get_delay: function () {
                // Gets the current delay in milliseconds
                return this._delay;
            },

            set_delay: function (value) {
                // Sets the current delay in milliseconds
                this._delay = value;
            },

            post: function (args) {
                // A method that can be directly attached to a delegate
                var ar = [];
                for (var i = 0; i < arguments.length; i++)
                    ar[i] = arguments[i];

                this.beginPost(ar, null, null);
            },

            beginPost: function (args, completeCallback, errorCallback) {
                // Posts a call to an async operation on this port

                // cancel any pending post
                this.cancel();

                // cache the call arguments
                this._callArgs = Array.clone(args || []);
                this._completeCallback = completeCallback;
                this._errorCallback = errorCallback;

                if (this._delay == -1) {
                    // if there is no delay (-1), complete synchronously
                    try {
                        this._oncomplete();
                    } finally {
                        this._completedSynchronously = true;
                    }
                } else {
                    // complete the post on a seperate call after a delay
                    this._timer = setTimeout(this._oncomplete$delegate, this._delay);
                }
            },

            cancel: function () {
                if (this._timer) {
                    clearTimeout(this._timer);
                    this._timer = null;
                }

                this._callArgs = null;
                this._isComplete = false;
                this._asyncResult = null;
                this._completeCallback = null;
                this._errorCallback = null;
                this._exception = null;
                this._completedSynchronously = false;
            },

            call: function (args) {
                // Executes the deferred operation synchronously

                var ar = [];
                for (var i = 0; i < arguments.length; i++)
                    ar[i] = arguments[i];

                // cancel any pending post
                this.cancel();

                // cache the call arguments
                this._callArgs = ar;
                this._completeCallback = null;
                this._errorCallback = null;

                try {
                    this._oncomplete();
                } finally {
                    this._completedSynchronously = true;
                }

                if (this._exception)
                    throw this._exception;

                return this._asyncResult;
            },

            complete: function () {
                // Completes a pending post synchronously

                if (this._timer) {
                    try {
                        this._oncomplete();
                    } finally {
                        this._completedSynchronously = true;
                    }

                    return this._asyncResult;
                } else if (this._isComplete) {
                    return this._asyncResult;
                }
            },

            _oncomplete: function () {
                // Completes a pending post asynchronously

                var args = this._callArgs,
                    completeCallback = this._completeCallback,
                    errorCallback = this._errorCallback;

                // clear the post state
                this.cancel();
                try {
                    // call the post callback
                    if (args)
                        this._asyncResult = this._callback.apply(this._context, args);
                    else
                        this._asyncResult = this._callback.call(this._context);

                    this._isComplete = true;
                    this._completedSynchronously = false;

                    if (completeCallback)
                        completeCallback(this);
                } catch (e) {
                    this._isComplete = true;
                    this._completedSynchronously = false;
                    this._exception = e;

                    if (errorCallback)
                        if (errorCallback(this))
                            return;

                    if (this._throwExceptions)
                        throw e;
                }
            }
        }

        Sys.Extended.UI.DeferredOperation.registerClass("Sys.Extended.UI.DeferredOperation");

    }




    if (window.Sys && Sys.loader) {
        Sys.loader.registerScript(scriptName, null, execute);
    }
    else {
        execute();
    }



})();